﻿using AppMachine.Controls.ValidationRules;
using AppMachine.Domain.LogicCom;
using AppMachine.Domain.LogicCom.AppComs;
using AppMachine.EntityFrameworkCore.Repositories.LogicCom;
using AppMachine.EntityFrameworkCore.Repositories.PerpDev;
using PerpheralDevice;
using PerpheralDevice.Units;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;

namespace AppMachine.Controls.Primitive {
    /// <summary>
    /// 输入、输出、伺服 原子控件基类
    /// </summary>
    public abstract class Prim : Control {

        protected AppComPrim mfAppComPrim = null;
        public override void OnApplyTemplate() {
            base.OnApplyTemplate();

            if (this.GetTemplateChild("xNameCfg") is Button tempBtnCfg) {
                tempBtnCfg.Click += (sender, evt) => {
                    if (this.GetTemplateChild("xNamePopup") is Popup tempPopup) {
                        tempPopup.IsOpen = true;
                        this.Load();
                    }
                };
            }

            if (this.GetTemplateChild("xNameSaveConfig") is Button tempBtnSaveConfig) {
                tempBtnSaveConfig.Click += (sender, evt) => {
                    bool tempResult = this.Save();
                    if (this.GetTemplateChild("xNamePopup") is Popup tempPopup) {
                        tempPopup.IsOpen = !tempResult;
                    }
                };
            }

            if (this.GetTemplateChild("xNameComboBoxEndList") is ComboBox tempComboBoxEndList) {
                tempComboBoxEndList.DisplayMemberPath = "PerpDevName";
                tempComboBoxEndList.SelectedValuePath = "PerpDevID";
                if (this.GetTemplateChild("xNameComboBoxEndAddrList") is ComboBox tempComboBoxEndAddrList) {
                    tempComboBoxEndAddrList.DisplayMemberPath = "UnitID";
                    tempComboBoxEndAddrList.SelectedValuePath = "UnitID";
                }
                tempComboBoxEndList.ItemsSource = this.LoadPerpTypeItemsSource();
                tempComboBoxEndList.SelectionChanged += (sender, evt) => {
                    if (this.GetTemplateChild("xNameComboBoxEndAddrList") is ComboBox tempComboBoxEndAddrList) {
                        tempComboBoxEndAddrList.ItemsSource = this.LoadUnitTypeItemsSource(this.mfAppComPrim.PerpDev);
                        tempComboBoxEndAddrList.SelectedValue = null;
                        if (tempComboBoxEndList.SelectedValue.Equals(this.mfAppComPrim.PerpDevID)) {
                            tempComboBoxEndAddrList.SelectedValue = this.mfAppComPrim.PerpUnitID;
                        }
                    }
                    this.UpdateSource();
                };
            }

        }

        /// <summary>
        /// 加载包含某一分类(输入、输出、伺服)的外设集合
        /// </summary>
        /// <returns></returns>
        protected abstract IEnumerable<PerpDev> LoadPerpTypeItemsSource();
        /// <summary>
        /// 加载外设对应 的 原子组件某一分类(输入、输出、伺服)集合
        /// </summary>
        /// <param name="perpDev">外设</param>
        /// <returns></returns>
        protected abstract IEnumerable<PerpDevUnit> LoadUnitTypeItemsSource(PerpDev perpDev);

        protected void UpdateTarget() {
            this.GetOfType<TextBox>().ForEach(tempTextBox => {
                BindingOperations.GetBindingExpression(tempTextBox, TextBox.TextProperty)?.UpdateTarget();
            });
            this.GetOfType<ComboBox>().ForEach(tempComboBox => {
                BindingOperations.GetBindingExpression(tempComboBox, TextBox.TextProperty)?.UpdateTarget();
            });
        }
        protected bool UpdateSource() {
            this.GetOfType<TextBox>().ForEach(tempTextBox => {
                var tempBindingExpression = BindingOperations.GetBindingExpression(tempTextBox, TextBox.TextProperty);
                if (tempBindingExpression != null) {
                    Validation.ClearInvalid(BindingOperations.GetBindingExpression(tempTextBox, TextBox.TextProperty));
                    tempBindingExpression.UpdateSource();
                }
                var tempBinding = BindingOperations.GetBinding(tempTextBox, TextBox.TextProperty);
                if (tempBinding != null) {
                    if (tempBinding.ValidationRules.FirstOrDefault(it => it.GetType().Equals(typeof(ValidationRuleComTagName))) is ValidationRuleComTagName tempValidationRuleComTagName) {
                        tempValidationRuleComTagName.ComID = this.ComID;
                    }
                }
            });
            this.GetOfType<ComboBox>().ForEach(tempComboBox => {
                var tempBindingExpression = BindingOperations.GetBindingExpression(tempComboBox, ComboBox.SelectedValueProperty);
                if (tempBindingExpression != null) {
                    Validation.ClearInvalid(BindingOperations.GetBindingExpression(tempComboBox, ComboBox.SelectedValueProperty));
                    tempBindingExpression.UpdateSource();
                }
            });


            return !(this.GetOfType<TextBox>().Any(tempTextBox => Validation.GetHasError(tempTextBox))
                || this.GetOfType<ComboBox>().Any(tempComboBox => Validation.GetHasError(tempComboBox)));
        }

        /// <summary>
        /// 1. 优先根据ComID加载组件；2. 如果加载失败，再根据 PerpDevID、PerpUnitID加载组件
        /// </summary>
        /// <returns></returns>
        protected virtual void Load() {
            if (this.mfAppComPrim == null) {
                if (!string.IsNullOrWhiteSpace(this.PerpDevID) && !string.IsNullOrWhiteSpace(this.PerpUnitID)) {
                    this.mfAppComPrim ??= AppComRepository.GetInstance().GetOrAdd<AppComPrim>(this.PerpDevID, this.PerpUnitID);
                    if (this.mfAppComPrim != null) {
                        this.OnLoadCompleted();
                    }
                }
            }
        }
        protected virtual void OnLoadCompleted() { }

        /// <summary>
        /// 保存应用组件配置
        /// </summary>
        /// <returns></returns>
        protected virtual bool Save() {
            this.mfAppComPrim.DevIDSet(this.PerpDevID).UnitIDSet(this.PerpUnitID).TagNameSet(this.TagName).Save();
            return true;
        }
                
        public string ComID {
            get { return (string)GetValue(ComIDProperty); }
            set { SetValue(ComIDProperty, value); }
        }
        public static readonly DependencyProperty ComIDProperty =
            DependencyProperty.Register("ComID", typeof(string), typeof(Prim), new PropertyMetadata(default(string), (d, e) => {
                if (d is Prim tempPrim) {
                    App.Current.Dispatcher.BeginInvoke(() => {
                        tempPrim.mfAppComPrim = AppComRepository.GetInstance().GetByID<AppComPrim>(tempPrim.ComID);
                        if (tempPrim.mfAppComPrim != null) {
                            tempPrim.OnLoadCompleted();
                        }
                    });
                }
            }));

        /// <summary>
        /// 应用组件对应的外设ID(该属性暂时仅针对原子组件 DI,DO,伺服)
        /// </summary>
        public string PerpDevID {
            get { return (string)GetValue(PerpDevIDProperty); }
            set { SetValue(PerpDevIDProperty, value); }
        }
        public static readonly DependencyProperty PerpDevIDProperty =
            DependencyProperty.Register("PerpDevID", typeof(string), typeof(Prim), new PropertyMetadata(default(string), (d, e) => { }));

        /// <summary>
        /// 应用组件对应的外设点位ID(该属性暂时仅针对原子组件 DI,DO,伺服)
        /// </summary>
        public string PerpUnitID {
            get { return (string)GetValue(PerpUnitIDProperty); }
            set { SetValue(PerpUnitIDProperty, value); }
        }
        public static readonly DependencyProperty PerpUnitIDProperty =
            DependencyProperty.Register("PerpUnitID", typeof(string), typeof(Prim), new PropertyMetadata(default(string), (d, e) => {}));

        private const string CfgEnabledDesc = $"是否允许用户配置DI\n1. 配置DI信号的来源\n2. 配置DI的使用设置";
        /// <summary>
        /// 是否允许用户配置DI
        /// 1. 配置DI信号的来源
        /// 2. 配置DI的使用设置
        /// </summary>
        [Description(CfgEnabledDesc)]
        public bool CfgEnabled {
            get { return (bool)GetValue(CfgEnabledProperty); }
            set { SetValue(CfgEnabledProperty, value); }
        }
        public static readonly DependencyProperty CfgEnabledProperty =
            DependencyProperty.Register("CfgEnabled", typeof(bool), typeof(Prim), new PropertyMetadata(default(bool), (d, e) => { }));

        public string TagName {
            get { return (string)GetValue(TagNameProperty); }
            set { SetValue(TagNameProperty, value); }
        }
        public static readonly DependencyProperty TagNameProperty =
            DependencyProperty.Register("TagName", typeof(string), typeof(Prim), new PropertyMetadata("XXX", (d, e) => { }));

    }
}
